package com.yzion.baselib.imageloader

import android.app.Activity
import android.content.Context
import android.graphics.drawable.Drawable
import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.annotation.IntRange
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.RequestManager
import com.bumptech.glide.integration.webp.decoder.WebpDrawable
import com.bumptech.glide.integration.webp.decoder.WebpDrawableTransformation
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.MultiTransformation
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.CircleCrop
import com.bumptech.glide.load.resource.bitmap.FitCenter
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import jp.wasabeef.glide.transformations.BlurTransformation

/**
 * ZJJ
 * 统一配置的图片加载工具，支持加载圆形图片，圆角图片，图片高斯模糊等
 * 使用Glide库加载图片
 */
open class ImageLoader {

    private fun getRequestManager(context: Context): RequestManager {
        return if (context is Activity) {
            Glide.with(context)
        } else Glide.with(context)
    }

    //-----------加载图片-----------//

    /**
     * 加载图片
     */
    fun load(model: Any?, target: ImageView, options: Options? = Options.defaultOptions()) {
        getRequestManager(target.context)
                .load(model)
                .apply(wrapScaleType(options))
                .timeout(TIME_OUT)
                .transition(DrawableTransitionOptions.withCrossFade())
                .into(target)
    }

    /**
     * 加载图片+回调
     */
    fun loadCallback(
            context: Context,
            model: Any?,
            callback: LoadCallback?,
            options: Options? = Options.defaultOptions()
    ) {
        getRequestManager(context)
                .load(model)
                .apply(wrapScaleType(options))
                .timeout(TIME_OUT)
                .transition(DrawableTransitionOptions.withCrossFade())
                .addListener(object : RequestListener<Drawable?> {
                    override fun onLoadFailed(
                            e: GlideException?,
                            model: Any,
                            target: Target<Drawable?>,
                            isFirstResource: Boolean
                    ): Boolean {
                        callback?.onLoadFailed()
                        return false
                    }

                    override fun onResourceReady(
                            resource: Drawable?,
                            model: Any,
                            target: Target<Drawable?>,
                            dataSource: DataSource,
                            isFirstResource: Boolean
                    ): Boolean {
                        callback?.onLoadReady(resource)
                        return false
                    }
                }).preload()
    }

    //加载图片+高斯模糊
    fun loadBlur(
            url: Any?,
            target: ImageView,
            @IntRange(from = 0, to = 25) blur: Int,
            options: Options? = Options.defaultOptions()
    ) {
        val requestOptions = wrapScaleType(options).transform(BlurTransformation(blur))
        getRequestManager(target.context)
                .load(url)
                .apply(requestOptions)
                .timeout(TIME_OUT)
                .transition(DrawableTransitionOptions.withCrossFade())
                .into(target)
    }

    //-----------加载动画图片-----------//

    /**
     * 加载webp动画图片
     */
    fun loadWebp(model: Any?, target: ImageView) {
        val requestOptions = RequestOptions()
                .diskCacheStrategy(DiskCacheStrategy.ALL)
        val fitCenter = FitCenter()
        getRequestManager(target.context)
                .load(model)
                .apply(requestOptions)
                .timeout(TIME_OUT)
                .optionalTransform(fitCenter)
                .optionalTransform(WebpDrawable::class.java, WebpDrawableTransformation(fitCenter))
                .into(target)
    }

    //-----------加载圆形图片-----------//

    /**
     * 加载圆形图片
     */
    fun loadCircle(url: Any?, target: ImageView, options: Options? = Options.defaultOptions()) {
        val requestOptions = wrapScaleType(options).optionalCircleCrop()
        getRequestManager(target.context)
                .load(url)
                .apply(requestOptions)
                .timeout(TIME_OUT)
                .transition(DrawableTransitionOptions.withCrossFade())
                .into(target)
    }

    /**
     * 加载圆形图片+回调
     */
    fun loadCircleCallback(
            context: Context,
            url: Any?,
            callback: LoadCallback?,
            options: Options? = Options.defaultOptions()
    ) {
        val requestOptions = wrapScaleType(options).optionalCircleCrop()
        getRequestManager(context)
                .load(url)
                .apply(requestOptions)
                .timeout(TIME_OUT)
                .transition(DrawableTransitionOptions.withCrossFade())
                .listener(object : RequestListener<Drawable?> {
                    override fun onLoadFailed(
                            e: GlideException?,
                            model: Any,
                            target: Target<Drawable?>,
                            isFirstResource: Boolean
                    ): Boolean {
                        callback?.onLoadFailed()
                        return true
                    }

                    override fun onResourceReady(
                            resource: Drawable?,
                            model: Any,
                            target: Target<Drawable?>,
                            dataSource: DataSource,
                            isFirstResource: Boolean
                    ): Boolean {
                        callback?.onLoadReady(resource)
                        return true
                    }
                }).submit()
    }

    /**
     * 加载圆形图片+高斯模糊
     */
    fun loadCircleBlur(
            url: Any?,
            target: ImageView,
            @IntRange(from = 0, to = 25) blur: Int,
            options: Options? = Options.defaultOptions()
    ) {
        val multiTransformation =
                MultiTransformation(CenterCrop(), CircleCrop(), BlurTransformation(blur))
        val requestOptions = wrapScaleType(options).transform(multiTransformation)
        getRequestManager(target.context)
                .load(url)
                .apply(requestOptions)
                .timeout(TIME_OUT)
                .transition(DrawableTransitionOptions.withCrossFade())
                .into(target)
    }

    //-----------加载圆角图片-----------//

    /**
     *  加载圆角图片
     */
    fun loadCorner(
            url: Any?,
            target: ImageView,
            radius: Int,
            options: Options? = Options.defaultOptions()
    ) {
        //设置图片圆角角度
        val multiTransformation = MultiTransformation(CenterCrop(), RoundedCorners(radius))
        val requestOptions = wrapScaleType(options).transform(multiTransformation)
        getRequestManager(target.context)
                .load(url)
                .apply(requestOptions)
                .timeout(TIME_OUT)
                .transition(DrawableTransitionOptions.withCrossFade())
                .into(target)
    }

    /**
     * 加载圆角图片+高斯模糊
     */
    fun loadCornerBlur(
            url: Any?,
            target: ImageView,
            radius: Int,
            @IntRange(from = 0, to = 25) blur: Int,
            options: Options? = Options.defaultOptions()
    ) {
        //设置图片圆角角度
        val multiTransformation =
                MultiTransformation(CenterCrop(), RoundedCorners(radius), BlurTransformation(blur))
        val requestOptions = wrapScaleType(options).transform(multiTransformation)
        getRequestManager(target.context)
                .load(url)
                .apply(requestOptions)
                .timeout(TIME_OUT)
                .transition(DrawableTransitionOptions.withCrossFade())
                .into(target)
    }

    /**
     * 加载圆角图片+回调
     */
    fun loadCornerCallback(
            context: Context,
            url: String?,
            radius: Int,
            callback: LoadCallback?,
            options: Options? = Options.defaultOptions()
    ) {
        //设置图片圆角角度
        val multiTransformation = MultiTransformation(CenterCrop(), RoundedCorners(radius))
        val requestOptions = wrapScaleType(options).transform(multiTransformation)
        getRequestManager(context)
                .load(url)
                .apply(requestOptions)
                .timeout(TIME_OUT)
                .transition(DrawableTransitionOptions.withCrossFade())
                .listener(object : RequestListener<Drawable?> {
                    override fun onLoadFailed(
                            e: GlideException?,
                            model: Any,
                            target: Target<Drawable?>,
                            isFirstResource: Boolean
                    ): Boolean {
                        callback?.onLoadFailed()
                        return true
                    }

                    override fun onResourceReady(
                            resource: Drawable?,
                            model: Any,
                            target: Target<Drawable?>,
                            dataSource: DataSource,
                            isFirstResource: Boolean
                    ): Boolean {
                        callback?.onLoadReady(resource)
                        return true
                    }
                }).submit()
    }

    fun clearMemoryCache(context: Context) {
        Glide.get(context).clearMemory()
    }

    fun clearDiskCache(context: Context) {
        Glide.get(context).clearDiskCache()
    }

    fun resume(context: Context) {
        getRequestManager(context).resumeRequests()
    }

    fun pause(context: Context) {
        getRequestManager(context).pauseRequests()
    }

    private fun wrapScaleType(options: Options?): RequestOptions {
        var request = RequestOptions()
                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                .priority(Priority.HIGH)
                .centerCrop()

        if (options != null) {
            if (options.loadingResId != Options.RES_NONE) {
                request = request.placeholder(options.loadingResId)
            }
            if (options.errorResId != Options.RES_NONE) {
                request = request.error(options.errorResId)
            }
        }
        return request
    }

    class Options(
            @DrawableRes val loadingResId: Int = RES_NONE,
            @DrawableRes val errorResId: Int = RES_NONE
    ) {

        companion object {
            const val RES_NONE = -1

            fun defaultOptions(): Options {
                return Options(RES_NONE, RES_NONE)
            }
        }

    }

    abstract class LoadCallback {
        open fun onLoadFailed() {}
        abstract fun onLoadReady(drawable: Drawable?)
    }

    companion object {
        private val imageLoader: ImageLoader by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            ImageLoader()
        }

        @JvmStatic
        fun get(): ImageLoader {
            return imageLoader
        }

        const val ASSETS_PATH = "file:///android_asset/"
        var TIME_OUT = 10 * 1000
    }
}